package logtail_enc

import (
	"time"
	"strings"
	"github.com/aliyun/aliyun-log-go-sdk"
	"github.com/aliyun/aliyun-log-go-sdk/example/util"
	//"fmt"
	log "github.com/cihub/seelog"
)


type StLogStore struct {
	ProjectName			string
	LogStoreName		string
	ConfigName			string
	LogFileName			string
	LogFilePath			string
	UrlReg              string
	UrlKeys				[]string
	LogSample			string
}


//通过searchkey searchCursor shardid获取数据
//func (ls *StLogStore)GetCursorLogs(searchKey string, searchCursor string, shardid int) ( cursor string, value []*sls.LogContent, stime int64, err error) {
func (ls *StLogStore)GetCursorLogs(searchCursor string, shardid int) ( cursor string, value []*sls.LogContent, stime int64, err error) {

	var beginCursor 	string
	var nextCursor 		string
	var loggrouplist 	*sls.LogGroupList

	//fmt.Println("search cursor:", searchCursor)
	log.Debug("search cursor:", searchCursor)
	//if sh.ShardID == 0 {
	if len(searchCursor) > 0 {
		beginCursor = searchCursor
	} else {
		for retryTimes :=0; ; retryTimes ++ {
			if retryTimes > 5 {
				return
			}
			beginCursor, err = util.Client.GetCursor(ls.ProjectName, ls.LogStoreName, shardid, "begin")
			cursor = beginCursor
			if err != nil {
				//fmt.Printf("GetCursor(begin) fail, retry: %d, err:%v\n", retryTimes, err)
				log.Errorf("GetCursor(begin) fail, retry: %d, err:%v\n", retryTimes, err)
			} else {
				//fmt.Printf("GetCursor(begin) success\n")
				log.Debug("GetCursor(begin) success")
				cursor = beginCursor
				break
			}
			time.Sleep(200 * time.Millisecond)
		}
	}
	//fmt.Println("begin cursor:", beginCursor)

	// PullLogs API Ref: https://intl.aliyun.com/help/doc-detail/29025.htm
	loggrouplist, nextCursor, err = util.Client.PullLogs(ls.ProjectName, ls.LogStoreName, shardid, beginCursor, "", 1)
	cursor = nextCursor
	if err != nil {
		//fmt.Printf("PullLogs fail err: %s\n", err)
		log.Errorf("PullLogs fail err: %s", err)

		//handle exception here, you can add retryable erorrCode, set appropriate put_retry
		if strings.Contains(err.Error(), sls.READ_QUOTA_EXCEED) ||
			strings.Contains(err.Error(), sls.PROJECT_QUOTA_EXCEED) ||
			strings.Contains(err.Error(), sls.SHARD_READ_QUOTA_EXCEED) {
			//mayby you should split shard
			time.Sleep(1000 * time.Millisecond)
		} else if strings.Contains(err.Error(), sls.INTERNAL_SERVER_ERROR) ||
			strings.Contains(err.Error(), sls.SERVER_BUSY) {
			time.Sleep(200 * time.Millisecond)
		}
	}

	log.Debugf("shard: %d, begin_cursor: %s, end_cursor: %s, next_cursor: %s\n", shardid, beginCursor, "", nextCursor)
	for _, loggroup := range loggrouplist.LogGroups {
		for _, logs := range loggroup.Logs {
			stime = int64(logs.GetTime())
			value = logs.GetContents()
			return cursor, value, stime, nil
			//for _, content := range logs.Contents {
			//	//if content.GetKey() == "time" {
			//	//	stime = content.GetValue()
			//	//}
			//	if content.GetKey() == searchKey{
			//		log.Infof("key:%s, value:%s", content.GetKey(), content.GetValue())
			//		value = content.GetValue()
			//		content.Marshal()
			//		return  cursor, value, stime,nil
			//	}
			//}
		}
	}
	//fmt.Println("cursor:", cursor)
	log.Debugf("cursor:", cursor)

	return  cursor, value, stime, nil
}



// search logs from index on logstore begtime="2018-01-01 12:00:00"
func (ls *StLogStore)SearchLogs(query string, begtime int64, endtime int64) (content []map[string]string) {
	totalCount := int64(0)
	log.Infof("begtime:", begtime, " endtime:", endtime )

	for  {
		// GetHistograms API Ref: https://intl.aliyun.com/help/doc-detail/29030.htm
		ghResp, err := util.Client.GetHistograms(ls.ProjectName, ls.LogStoreName, "", int64(begtime), int64(endtime), query)
		if err != nil {
			//fmt.Printf("GetHistograms fail, err: %v\n", err)
			log.Errorf("GetHistograms fail, err: %v", err)
			time.Sleep(10 * time.Millisecond)
			continue
		}
		//fmt.Println(ghResp)
		log.Infof("complete: %s, count: %d, histograms: %v", ghResp.Progress, ghResp.Count, ghResp.Histograms)
		totalCount += ghResp.Count
		if ghResp.Progress == "Complete"{
			break
		}
	}
	//fmt.Println("total count:", totalCount)
	log.Debugf("total count:", totalCount)
	offset := int64(0)
	for offset < totalCount{
		glResp, err := util.Client.GetLogs(ls.ProjectName, ls.LogStoreName, "", int64(begtime), int64(endtime), query, 100, offset, false)
		if err != nil{
			//fmt.Printf("GetLogs fail, err:%v\n", err)
			log.Errorf("GetLogs fail, err:%v", err)
			time.Sleep(10*time.Millisecond)
			continue
		}
		log.Debugf("Progress:%s, Count:%d, offset: %d\n", glResp.Progress, glResp.Count, offset)
		offset += glResp.Count
		if glResp.Count > 0{
			//fmt.Printf("logs:%v\n", glResp.Logs)
			log.Infof("logs:%v", glResp.Logs)
			content = glResp.Logs
			for i := range glResp.Logs {
				//(glResp.Logs[i])
				log.Info(glResp.Logs[i]["callback"])
			}
		}
		if glResp.Progress == "Complete" && glResp.Count == 0 {
			break
		}
	}

	return content
}

